Instance Chains
from PureScriptの型クラス
Instance Chains: Type Class Programming Without Overlapping Instances
論文
こういう構文
code:purs(hs)
instance showString :: MyShow String where
myShow s = s
else instance showBoolean :: MyShow Boolean where
myShow true = "true"
myShow false = "false"
instance宣言にelseが付いているmrsekut.icon
型クラスの引数が重複している場合に、どれを選択すれば良いかを明示することができる
型クラスの引数は複数取り得るがまずは1つについて見てみる
ここに載っている例
code:purs(hs)
class MyShow a where
myShow :: a -> String
instance showString :: MyShow String where
myShow s = s
else instance showBoolean :: MyShow Boolean where
myShow true = "true"
myShow false = "false"
else instance showA :: MyShow a where
myShow _ = "Invalid"
data MysteryItem = MysteryItem
ここではMyShowに対してのinstanceを複数個宣言している
instance chainがないと困るのは↓この定義があるせい
code:purs(hs)
instance showA :: MyShow a where
myShow _ = "Invalid"
任意の型aに対して、MyShowのinstanceを定義している
すると、MyShow Stringを考えたい場合にコンパイラは以下の2つの定義のどちらを採用すべきか自明でなくなる
code:purs(hs)
instance showString :: MyShow String where
myShow s = s
instance showA :: MyShow a where
myShow _ = "Invalid"
これは型エラーになる
MyShow Stringは、MyShow Stringでもあるし(当たり前)、MyShow aでもある
「上に書いたほうが優先順位が高い」というルールはない
そもそも別ファイルでも定義できるmrsekut.icon
そこでelse instanceを使うことで「上に書いたほうが優先順位が高い」として、これを明示することができる
myShow "hoge"の場合は、MyShow Stringの定義を採用し、
myShow 100の場合は、MyShow aの定義を採用することになる
multi-parameter type classに関しても同じで
ここで説明されているのがソレ
code:purs(hs)
class IsEqual (l :: Type) (r :: Type) (b :: Boolean) | l r -> b
instance isEqualRefl :: IsEqual l l True
else instance isEqualDiff :: IsEqual l r False
3引数型クラスのinstanceについて、第1引数と第2引数が同じ型かどうかで定義を分けている
#??
hsにもあるのだろうか?
https://www.haskell.org/onlinereport/haskell2010/haskellch4.html#x10-770004.3.2
これ?
https://mizunashi-mana.github.io/blog/posts/2020/03/coherent-typeclass-and-orphan-instance/
参考
documentation/Type-Classes.md at master · purescript/documentation
purs公式のdocs
説明がうすすぎると思う
PureScript: Instance chains and Overlapping Instances | LiamGoodacre
3引数型クラスを例に取った説明
簡潔だがdocsよりは詳しい
https://stackoverflow.com/questions/50290695/how-to-use-instance-chain-to-solve-overlapping